using System;
using System.Collections.Generic;
using System.Reflection;
using TestCases.CompareAssert.Core.Comparers.Interfaces;
using TestCases.CompareAssert.Core.Selectors;

namespace TestCases.CompareAssert.Core.Comparers.Members
{
    public class PropertiesComparer : MembersComparer<PropertyInfo>
    {
        public const string IdentifiableName = "PropertiesComparer";
        public const string PropertyEntity = "property";

        public PropertiesComparer()
        {            
        }
        
        public PropertiesComparer(ITypeSelector typeSelector) : base(typeSelector)
        {            
        }
        
        public PropertiesComparer(IObjectComparer comparer) : base(comparer)
        {
        }

        public PropertiesComparer(ITypeSelector typeSelector, IObjectComparer comparer) : base(typeSelector, comparer)
        {
        }

        public bool IgnoreReadOnly { get; set; }
        public override string EntityName { get { return PropertyEntity; } }
        public override string Name { get { return IdentifiableName; } }

        public bool IsValidProperty(PropertyInfo info)
        {
            return info.GetIndexParameters().Length == 0 && info.CanRead && (!IgnoreReadOnly || info.CanWrite);
        }

        public override IEnumerable<string> GetMemberNames(Type type, BindingFlags flags)
        {
            return ExtractMemberNames(Array.FindAll(type.GetProperties(flags), IsValidProperty));
        }

        public override PropertyInfo GetMember(Type type, string name, BindingFlags flags)
        {
            return type.GetProperty(name, flags);
        }

        public override object GetMemberValue(PropertyInfo member, object instance)
        {
            return member.GetValue(instance, null);
        }

    }
}